home *** CD-ROM | disk | FTP | other *** search
- /*
- * fdesign.c
- *
- * This file belongs to the goodies of the Forms Library.
- *
- * It contains the file selector.
- *
- * Written by: Mark Overmars and Trevor Paquette
- *
- * Version 2.2 b
- * Date: Jun 18, 1993
- */
-
- #include <malloc.h>
- #include <unistd.h>
- #include <strings.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <sys/time.h>
-
- #include "forms.h"
- /* the following is strictly for compilation on an Ultrix
- * with gcc
- */
- #if defined(__vax__) || defined(__STRICT_ANSI__)
- extern int scandir(const char *, struct dirent **[],
- int (*select)(struct dirent *),
- int (*howsort)(struct dirent **, struct dirent **));
- extern int alphasort(struct dirent **, struct dirent **);
- #endif
-
- static FL_FORM *fsform;
- static FL_OBJECT *messageobj, *selectionobj, *readyobj, *cancelobj,
- *selectobj, *directoryobj, *patternobj;
-
- static char fl_directory[256]; /* Current directory */
- static char fl_pattern[256]; /* Current pattern */
- static char fl_filename[256]; /* Current selected file name */
-
- /*------------------- Pattern matching --------------------------*/
- /* Adapted from Rich Salz. */
-
- static int do_matching(char *, char *);
-
- static int match_star(char *s, char *p)
- {
- int result;
- while( (result = do_matching(s, p)) == FALSE) /* gobble up * match */
- if(*++s == NULL) return -1;
- return result;
- }
-
- static int do_matching(char *s, char *p)
- /* match string "s" to pattern "p" */
- {
- int last, matched, reverse;
- for ( ; *p; s++, p++)
- {
- if(*s == NULL) return (*p == '*' && *++p == NULL ? TRUE : -1);
-
- switch(*p)
- { /* parse pattern */
- case '\\': /* Literal match with following character. */
- if(*s != *++p) return FALSE;
- continue;
-
- default : /*literal match*/
- if(*s != *p) return FALSE;
- continue;
-
- case '?' : /* Match anything. */
- continue;
-
- case '*' : /* Trailing star matches everything. */
- return (*++p ? match_star(s, p) : TRUE);
-
- case '[': /* [!....] means inverse character class. */
- if (reverse = p[1] == '!') p++;
-
- for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
- /* This next line requires a good C compiler. */
- /* range? (in bounds) (equal) */
- if((*p == '-') ? (*s <= *++p && *s >= last ) : (*s == *p))
- matched = TRUE;
-
- if(matched == reverse) return FALSE;
- continue;
- }
- }
- return *s == NULL;
- }
-
- static int wildmat(char *s, char *p)
- {
- if (*p == NULL && *s != '.') return TRUE;
- else if (*p == NULL) return FALSE;
- else if ( (*p == '?' || *p == '*' ) && *s == '.') return FALSE;
- else return do_matching(s, p) == TRUE;
- }
-
- static int match_pattern(struct dirent *file)
- {
- char tmpstr[256];
- struct stat fstat;
- strcpy(tmpstr,fl_directory);
- if (strlen(fl_directory)==0 || fl_directory[strlen(fl_directory)-1]!='/')
- strcat(tmpstr,"/");
- strcat(tmpstr,file->d_name);
- stat(tmpstr,&fstat);
- if (fstat.st_mode & S_IFDIR) return TRUE;
- return(wildmat(file -> d_name, fl_pattern));
- }
-
- /*------------------- Routine to correct directory ------------*/
-
- static void set_dirpath()
- /* Corrects the directory path. */
- {
- char tmpstr[256];
- int i,j,k;
- if (fl_directory[0] == NULL)
- strcpy(tmpstr,"/");
- else if (fl_directory[0] != '/')
- {
- getcwd(tmpstr,256);
- strcat(tmpstr,"/");
- strcat(tmpstr,fl_directory);
- }
- else
- strcpy(tmpstr,fl_directory);
- for (i=0; i < strlen(tmpstr); i++)
- {
- if (tmpstr[i] == '/' && tmpstr[i+1] == '.' &&
- (tmpstr[i+2] == '/' || tmpstr[i+2] == NULL))
- {
- for (j=i+2; tmpstr[j-1] != NULL; j++) tmpstr[j-2] = tmpstr[j];
- i--;
- }
- else if (tmpstr[i] == '/' && tmpstr[i+1] == '.' && tmpstr[i+2] == '.' &&
- (tmpstr[i+3] == '/' || tmpstr[i+3] == NULL))
- {
- if (i==0)
- {
- for (j=i+3; tmpstr[j-1] != NULL; j++) tmpstr[j-3] = tmpstr[j];
- i = -1;
- }
- else
- {
- for (k=i-1; tmpstr[k] != '/'; k--) ;
- for (j=i+3; tmpstr[j-1] != NULL; j++) tmpstr[j+k-i-3] = tmpstr[j];
- i = k-1;
- }
- }
- }
- if (tmpstr[0] == NULL) strcpy(tmpstr,"/");
- strcpy(fl_directory,tmpstr);
- fl_set_object_label(directoryobj,tmpstr);
- }
-
- /*------------------- Routine to fill in the browser ------------*/
-
- static void fillin_choices()
- /* Fills in the choices in the library based on the current directory and
- pattern. */
- {
- struct dirent **namelist;
- struct stat fstat;
- int i,fnumb;
- char tmpstr[256];
-
- /* Read the directory contents */
- fnumb = scandir(fl_directory, &namelist, match_pattern, alphasort);
- if (fnumb < 0)
- {
- fl_show_message("Cannot open:", fl_directory, "for reading.");
- fl_clear_browser(selectobj);
- return;
- }
-
- /* Fill in the browser */
- fl_freeze_form(fsform);
- fl_clear_browser(selectobj);
- for (i=0; i<fnumb; i++)
- {
- strcpy(tmpstr,fl_directory);
- if (strlen(fl_directory)==0 || fl_directory[strlen(fl_directory)-1]!='/')
- strcat(tmpstr,"/");
- strcat(tmpstr,namelist[i]->d_name);
- stat(tmpstr,&fstat);
- if (fstat.st_mode & S_IFDIR)
- sprintf(tmpstr,"D %s",namelist[i]->d_name);
- else
- sprintf(tmpstr," %s",namelist[i]->d_name);
- fl_add_browser_line(selectobj,tmpstr);
- free(namelist[i]);
- }
- fl_unfreeze_form(fsform);
- free(namelist);
- }
-
- /*----------------------- The Callback Routines -----------------*/
-
- static int lastline = 0;
- static long lastsec = 0;
- static long lastusec = 0;
-
- static int select_cb(FL_OBJECT *obj, long arg)
- /* user selected something in the selector */
- {
- char seltext[256];
- int dir, i;
- struct timeval tp;
- struct timezone tzp;
- strcpy(seltext,fl_get_browser_line(obj,fl_get_browser(obj)));
- dir = seltext[0] == 'D';
- for (i= 2; i<=strlen(seltext); i++) seltext[i-2] = seltext[i];
- if (dir)
- {
- if (strlen(fl_directory)== 0 || fl_directory[strlen(fl_directory)-1] != '/')
- strcat(fl_directory,"/");
- strcat(fl_directory,seltext);
- set_dirpath();
- fillin_choices();
- return 0;
- }
- else
- {
- fl_set_input(selectionobj,seltext);
- strcpy(fl_filename,seltext);
- gettimeofday(&tp,&tzp);
- if (lastline == fl_get_browser(obj))
- {
- if (1000000*(tp.tv_sec - lastsec) + (tp.tv_usec - lastusec) < 400000)
- return 1;
- }
- lastline = fl_get_browser(obj);
- lastsec = tp.tv_sec; lastusec = tp.tv_usec;
- return 0;
- }
- }
-
- static void directory_cb(FL_OBJECT *obj, long arg)
- /* User wants to change the directory */
- {
- strcpy(fl_directory,fl_show_input("Enter new directory:",fl_directory));
- set_dirpath();
- fillin_choices();
- }
-
- static void pattern_cb(FL_OBJECT *obj, long arg)
- /* User wants to change the pattern */
- {
- strcpy(fl_pattern,fl_show_input("Enter new pattern:",fl_pattern));
- fl_set_object_label(patternobj,fl_pattern);
- fillin_choices();
- }
-
- static void filename_cb(FL_OBJECT *obj, long arg)
- /* User changed the file name. Nothing needs to be done */
- {
- }
-
- /*------------------- The form definition -----------------------*/
-
- static void create_fs_form(void)
- {
- FL_OBJECT *obj;
- fsform = fl_bgn_form(FL_NO_BOX,530.0,460.0);
- obj = fl_add_box(FL_UP_BOX,0.0,0.0,530.0,460.0,"");
- fl_set_object_color(obj,12,47);
- messageobj = obj = fl_add_box(FL_BORDER_BOX,20.0,410.0,490.0,30.0,"A message");
- fl_set_object_color(obj,53,47);
- selectionobj = obj = fl_add_input(FL_NORMAL_INPUT,290.0,270.0,220.0,30.0,"file name");
- fl_set_object_boxtype(obj,FL_SHADOW_BOX);
- fl_set_object_color(obj,52,9);
- fl_set_object_align(obj,FL_ALIGN_TOP);
- fl_set_object_lstyle(obj,FL_BOLD_STYLE);
- fl_set_call_back(obj,filename_cb,0);
- readyobj = obj = fl_add_button(FL_RETURN_BUTTON,380.0,120.0,130.0,40.0,"Ready");
- cancelobj = obj = fl_add_button(FL_NORMAL_BUTTON,380.0,50.0,130.0,40.0,"Cancel");
- obj = fl_add_box(FL_SHADOW_BOX,20.0,20.0,240.0,300.0,"");
- selectobj = obj = fl_add_browser(FL_HOLD_BROWSER,20.0,20.0,240.0,300.0,"");
- fl_set_object_boxtype(obj,FL_BORDER_BOX);
- fl_set_object_color(obj,53,9);
- directoryobj = obj = fl_add_text(FL_NORMAL_TEXT,90.0,370.0,420.0,30.0,"Text");
- fl_set_object_boxtype(obj,FL_BORDER_BOX);
- fl_set_object_color(obj,52,47);
- fl_set_object_lsize(obj,10.000000);
- obj = fl_add_text(FL_NORMAL_TEXT,10.0,370.0,80.0,30.0,"directory");
- fl_set_object_align(obj,FL_ALIGN_RIGHT);
- fl_set_object_lstyle(obj,FL_BOLD_STYLE);
- patternobj = obj = fl_add_text(FL_NORMAL_TEXT,90.0,340.0,420.0,30.0,"Text");
- fl_set_object_boxtype(obj,FL_BORDER_BOX);
- fl_set_object_color(obj,52,47);
- fl_set_object_lsize(obj,10.000000);
- obj = fl_add_text(FL_NORMAL_TEXT,10.0,340.0,80.0,30.0,"pattern");
- fl_set_object_align(obj,FL_ALIGN_RIGHT);
- fl_set_object_lstyle(obj,FL_BOLD_STYLE);
- obj = fl_add_button(FL_HIDDEN_BUTTON,90.0,370.0,420.0,30.0,"");
- fl_set_object_lsize(obj,FL_SMALL_FONT);
- fl_set_call_back(obj,directory_cb,0);
- obj = fl_add_button(FL_HIDDEN_BUTTON,90.0,340.0,420.0,30.0,"");
- fl_set_call_back(obj,pattern_cb,0);
- fl_end_form();
- }
-
- /*----------------------- The Main Routine ----------------------*/
-
- static int created = 0; /* Whether form is created. */
- static char combined[512]; /* Used to contain the combined file name. */
-
- char *fl_show_file_selector(char message[],char dir[],char pat[],char fname[])
- /* Displays the file selector. Returns whether Ready was pressed. */
- {
- FL_OBJECT *obj;
-
- /* Create form if required. */
- if (!created)
- {
- strcpy(fl_directory,".");
- strcpy(fl_pattern,"*");
- fl_filename[0] = NULL;
- create_fs_form();
- created = 1;
- }
-
- /* Fill in the fields. */
- fl_set_object_label(messageobj,message);
- if (dir != NULL && dir[0] != '\0') strcpy(fl_directory,dir);
- if (pat != NULL && pat[0] != '\0') strcpy(fl_pattern,pat);
- if (fname != NULL && fname[0] != '\0') strcpy(fl_filename,fname);
- set_dirpath();
- fl_set_object_label(patternobj,fl_pattern);
- fl_set_input(selectionobj,fl_filename);
- fillin_choices();
-
- /* Show the form. */
- fl_set_browser_fontstyle(selectobj,FL_FIXED_STYLE);
- fl_set_object_focus(fsform,selectionobj);
- fl_deactivate_all_forms();
- fl_show_form(fsform,FL_PLACE_CENTER,FALSE,NULL);
- do {
- obj = fl_do_only_forms();
- if (obj == selectobj)
- if (select_cb(selectobj,0)) break;
- } while (obj != readyobj && obj != cancelobj);
- fl_hide_form(fsform);
- fl_activate_all_forms();
-
- /* Return value */
- if (obj == cancelobj) return NULL;
- strcpy(fl_filename,fl_get_input(selectionobj));
- strcpy(combined,fl_directory);
- if (strlen(fl_directory) == 0 || fl_directory[strlen(fl_directory)-1] != '/')
- strcat(combined,"/");
- strcat(combined,fl_filename);
- return combined;
- }
-
- char *fl_get_directory()
- /* returns a pointer to the directory */
- { return fl_directory; }
-
- char *fl_get_pattern()
- /* returns a pointer to the pattern */
- { return fl_pattern; }
-
- char *fl_get_filename()
- /* returns a pointer to the filename */
- { return fl_filename; }
-